package com.merryituxz.o2o.controller.shopadmin;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.merryituxz.o2o.dto.ShopAuthMapExecution;
import com.merryituxz.o2o.dto.UserAccessToken;
import com.merryituxz.o2o.dto.WechatInfo;
import com.merryituxz.o2o.entity.PersonInfo;
import com.merryituxz.o2o.entity.Shop;
import com.merryituxz.o2o.entity.ShopAuthMap;
import com.merryituxz.o2o.entity.WechatAuth;
import com.merryituxz.o2o.enums.ShopAuthMapStateEnum;
import com.merryituxz.o2o.service.PersonInfoService;
import com.merryituxz.o2o.service.ShopAuthMapService;
import com.merryituxz.o2o.service.WechatAuthService;
import com.merryituxz.o2o.util.CodeUtil;
import com.merryituxz.o2o.util.HttpServletRequestUtil;
import com.merryituxz.o2o.util.wechat.WechatUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/shopadmin")
public class ShopAuthManagementController {
    @Autowired
    private ShopAuthMapService shopAuthMapService;
    @Autowired
    private WechatAuthService wechatAuthService;
    @Autowired
    private PersonInfoService personInfoService;

    /**
     * 列出店铺授权信息
     *
     * @param request
     * @return
     */
    @GetMapping("/listshopauthmapsbyshop")
    @ResponseBody
    public Map<String, Object> listShopAuthMapsByShop(HttpServletRequest request) {
        Map<String, Object> modelMap = new HashMap<>();
        int pageIndex = HttpServletRequestUtil.getInt(request, "pageIndex");
        int pageSize = HttpServletRequestUtil.getInt(request, "pageSize");
        Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
        if (pageIndex > -1 && pageSize > -1 && currentShop != null && currentShop.getShopId() != null) {
            ShopAuthMapExecution shopAuthMapExecution =
                    shopAuthMapService.listShopAuthMapByShopId(currentShop.getShopId(), pageIndex, pageSize);
            modelMap.put("shopAuthMapList", shopAuthMapExecution.getShopAuthMapList());
            modelMap.put("count", shopAuthMapExecution.getCount());
            modelMap.put("success", true);
        } else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "empty pageIndex or pageSize or shopId");
        }
        return modelMap;
    }

    /**
     * 通过shopAuthId获取授权信息
     *
     * @param shopAuthId
     * @return
     */
    @GetMapping("/getshopauthmapbyid")
    @ResponseBody
    public Map<String, Object> getShopAuthMapById(@RequestParam Long shopAuthId) {
        Map<String, Object> modelMap = new HashMap<>();
        if (shopAuthId != null && shopAuthId > -1) {
            ShopAuthMap shopAuthMap = shopAuthMapService.getShopAuthMapById(shopAuthId);
            modelMap.put("shopAuthMap", shopAuthMap);
            modelMap.put("success", true);
        } else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "empty shopAuthId");
        }
        return modelMap;
    }

    @PostMapping("/modifyshopauthmap")
    @ResponseBody
    public Map<String, Object> modifyShopAuthMap(String shopAuthMapStr, HttpServletRequest request) {
        Map<String, Object> modelMap = new HashMap<>();
        // 判断当前操作类型是授权编辑还是删除/恢复授权
        // 授权操作需要校验验证码
        boolean statusChange = HttpServletRequestUtil.getBoolean(request, "statusChange");
        if (!statusChange && !CodeUtil.checkVerifyCode(request)) {
            modelMap.put("success", false);
            modelMap.put("errMsg", "输入了错误的验证码");
            return modelMap;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        ShopAuthMap shopAuthMap = null;
        try {
            // 将前端post的shopAuthMapStr转为实体类
            shopAuthMap = objectMapper.readValue(shopAuthMapStr, ShopAuthMap.class);
        } catch (Exception e) {
            modelMap.put("success", false);
            modelMap.put("errMsg", e.getMessage());
            return modelMap;
        }
        if (shopAuthMap != null && shopAuthMap.getShopAuthId() != null) {
            try {
                if (!CheckPermission(shopAuthMap.getShopAuthId())) {
                    modelMap.put("success", false);
                    modelMap.put("errMsg", "无法对店家本身权限进行操作(已是店铺最高权限)");
                    return modelMap;
                }
                ShopAuthMapExecution shopAuthMapExecution = shopAuthMapService.modifyShopAuthMap(shopAuthMap);
                if (shopAuthMapExecution.getState() == ShopAuthMapStateEnum.SUCCESS.getState()) {
                    modelMap.put("success", true);
                } else {
                    modelMap.put("success", false);
                    modelMap.put("errMsg", shopAuthMapExecution.getStateInfo());
                }
            } catch (RuntimeException e) {
                modelMap.put("success", false);
                modelMap.put("errMsg", e.toString());
                return modelMap;
            }
        } else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "请输入要修改的授权信息");
            return modelMap;
        }
        return modelMap;
    }

    /**
     * 检查是否可以编辑授权信息
     * 无法编辑店主自身的信息
     *
     * @param shopAuthId
     * @return
     */
    private boolean CheckPermission(Long shopAuthId) {
        ShopAuthMap curPerson = shopAuthMapService.getShopAuthMapById(shopAuthId);
        // 若是店家本身0，不能操作
        if (curPerson.getTitleFlag() == 0) {
            return false;
        } else {
            return true;
        }
    }

    // 微信获取用户信息的api前缀
    private static String urlPrefix;
    // 微信获取用户信息的api中间部分
    private static String urlMiddle;
    // 微信获取用户信息的api后缀
    private static String urlSuffix;
    // 微信回传给的响应添加授权信息的url
    private static String authUrl;

    @Value("${wechat.prefix}")
    public void setUrlPrefix(String urlPrefix) {
        ShopAuthManagementController.urlPrefix = urlPrefix;
    }

    @Value("${wechat.middle}")
    public void setUrlMiddle(String urlMiddle) {
        ShopAuthManagementController.urlMiddle = urlMiddle;
    }

    @Value("${wechat.suffix}")
    public void setUrlSuffix(String urlSuffix) {
        ShopAuthManagementController.urlSuffix = urlSuffix;
    }

    @Value("${wechat.auth.url}")
    public void setAuthUrl(String authUrl) {
        ShopAuthManagementController.authUrl = authUrl;
    }

    /**
     * 生成带有URL的二维码
     *
     * @param request
     * @param response
     */
    @GetMapping("/generateqrcode4shopauth")
    @ResponseBody
    public void generateQRCode4ShopAuth(HttpServletRequest request, HttpServletResponse response) {
        Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
        if (currentShop != null && currentShop.getShopId() != null) {
            // 获取当前时间戳以保证二维码的时间有效性
            long timeStamp = System.currentTimeMillis();
            String content = "{aaashopIdaaa:" + currentShop.getShopId() + ",aaacreateTimeaaa:" + timeStamp + "}";
            try {
                String url = urlPrefix + authUrl + urlMiddle + URLEncoder.encode(content, "UTF-8") + urlSuffix;
                // 生成二维码
                BitMatrix qRcodeImg = CodeUtil.generateQRCodeStream(url, response);
                // 将二维码以图片流的形式输出到前端
                MatrixToImageWriter.writeToStream(qRcodeImg, "png", response.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据微信回传的参数添加店铺的授权信息
     *
     * @param request
     * @param response
     * @return
     */
    @GetMapping("/addshopauthmap")
    public String addShopAuthMap(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        // 从request里获取微信用户信息
        WechatAuth auth = getEmployeeInfo(request);
        if (auth != null) {
            // 根据userId获取用户信息
            PersonInfo user = personInfoService.getPersonInfoById(auth.getPersonInfo().getUserId());
            request.getSession().setAttribute("user", user);
            // 解码微信回传来的自定义参数state[generateQRCode4ShopAuth中编码]
            String qrCodeinfo = new String(
                    URLDecoder.decode(HttpServletRequestUtil.getString(request, "state"), "UTF-8")
            );
            ObjectMapper objectMapper = new ObjectMapper();
            WechatInfo wechatInfo = null;
            try {
                wechatInfo = objectMapper.readValue(qrCodeinfo.replace("aaa", "\""), WechatInfo.class);
            } catch (Exception e) {
                return "shop/operationfail";
            }
            // 检查二维码是否已过期
            if (!checkQRCodeInfo(wechatInfo)) {
                return "shop/operationfail";
            }

            // 去重校验, 获取店铺下所有授权信息并检测是否重复
            ShopAuthMapExecution allMapList = shopAuthMapService.listShopAuthMapByShopId(
                    wechatInfo.getShopId(), 1, 999
            );
            List<ShopAuthMap> shopAuthMapList = allMapList.getShopAuthMapList();
            for (ShopAuthMap shopAuthMap : shopAuthMapList) {
                if (shopAuthMap.getEmployee().getUserId() == user.getUserId()) {
                    return "shop/operationfail";
                }
            }

            // 根据获取到的内容添加微信授权信息
            try {
                ShopAuthMap shopAuthMap = new ShopAuthMap();
                Shop shop = new Shop();
                shop.setShopId(wechatInfo.getShopId());
                shopAuthMap.setShop(shop);
                shopAuthMap.setEmployee(user);
                shopAuthMap.setTitle("员工");
                shopAuthMap.setTitleFlag(1);
                ShopAuthMapExecution shopAuthMapExecution = shopAuthMapService.addShopAuthMap(shopAuthMap);
                if (shopAuthMapExecution.getState() == ShopAuthMapStateEnum.SUCCESS.getState()) {
                    return "shop/operationsuccess";
                } else {
                    return "shop/operationfail";
                }
            } catch (RuntimeException e) {
                return "shop/operationfail";
            }
        }
        return "shop/operationfail";
    }

    /**
     * 根据二维码携带的createTime判断是否超过了10分钟, 超过10分钟则认为过期
     *
     * @param wechatInfo
     * @return
     */
    private boolean checkQRCodeInfo(WechatInfo wechatInfo) {
        if (wechatInfo != null && wechatInfo.getShopId() != null && wechatInfo.getCreateTime() != null) {
            long now = System.currentTimeMillis();
            if (now - wechatInfo.getCreateTime() <= 600000) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    /**
     * 根据微信回传的code获取用户信息
     *
     * @param request
     * @return
     */
    private WechatAuth getEmployeeInfo(HttpServletRequest request) {
        String code = request.getParameter("code");
        WechatAuth auth = null;
        if (code != null) {
            UserAccessToken token;
            try {
                token = WechatUtil.getUserAccessToken(code);
                String openId = token.getOpenId();
                request.getSession().setAttribute("openId", openId);
                auth = wechatAuthService.getWechatAuthByOpenId(openId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return auth;
    }
}
